/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use mHost file
 * except in compliance with the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package com.android.systemui.qs.tileimpl;

import android.content.Context;
import android.os.Build;
import android.os.SystemProperties;
import android.util.Log;
import android.view.ContextThemeWrapper;

import com.android.internal.telephony.TelephonyProperties;

import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tiles.AirplaneModeTile;
import com.android.systemui.qs.tiles.BatterySaverTile;
import com.android.systemui.qs.tiles.BluetoothTile;
import com.android.systemui.qs.tiles.CastTile;
import com.android.systemui.qs.tiles.CellularTile;
import com.android.systemui.qs.tiles.ColorInversionTile;
import com.android.systemui.qs.tiles.DataSaverTile;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.FlashlightTile;
import com.android.systemui.qs.tiles.HotspotTile;
import com.android.systemui.qs.tiles.LocationTile;
import com.android.systemui.qs.tiles.LteServiceTile;
import com.android.systemui.qs.tiles.NfcTile;
import com.android.systemui.qs.tiles.NightDisplayTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.qs.tiles.ScreenRecordTile;
import com.android.systemui.qs.tiles.UiModeNightTile;
import com.android.systemui.qs.tiles.UserTile;
import com.android.systemui.qs.tiles.VolteTile;
import com.android.systemui.qs.tiles.VoWifiTile;
import com.android.systemui.qs.tiles.WifiTile;
import com.android.systemui.qs.tiles.WorkModeTile;
import com.android.systemui.util.leak.GarbageMonitor;

import com.unisoc.systemui.qs.tiles.LongScreenshotTile;
import com.unisoc.systemui.qs.tiles.ScreenshotTile;
import com.unisoc.systemui.qs.tiles.SuperBatteryTile;
import com.unisoc.systemui.superpower.UnisocPowerManagerUtil;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;

import dagger.Lazy;

@Singleton
public class QSFactoryImpl implements QSFactory {

    private static final String TAG = "QSFactory";
    private static final String MODEM_CONFIG_PROP = "persist.vendor.radio.modem.config";
    private static final String LTE_INDICATOR = "L";

    private final Provider<WifiTile> mWifiTileProvider;
    private final Provider<BluetoothTile> mBluetoothTileProvider;
    private final Provider<CellularTile> mCellularTileProvider;
    private final Provider<DndTile> mDndTileProvider;
    private final Provider<ColorInversionTile> mColorInversionTileProvider;
    private final Provider<AirplaneModeTile> mAirplaneModeTileProvider;
    private final Provider<WorkModeTile> mWorkModeTileProvider;
    private final Provider<RotationLockTile> mRotationLockTileProvider;
    private final Provider<FlashlightTile> mFlashlightTileProvider;
    private final Provider<LongScreenshotTile> mLongScreenshotTileProvider;
    private final Provider<ScreenshotTile> mScreenshotTileProvider;
    private final Provider<LocationTile> mLocationTileProvider;
    private final Provider<CastTile> mCastTileProvider;
    private final Provider<HotspotTile> mHotspotTileProvider;
    private final Provider<UserTile> mUserTileProvider;
    private final Provider<BatterySaverTile> mBatterySaverTileProvider;
    private final Provider<DataSaverTile> mDataSaverTileProvider;
    private final Provider<NightDisplayTile> mNightDisplayTileProvider;
    private final Provider<NfcTile> mNfcTileProvider;
    private final Provider<GarbageMonitor.MemoryTile> mMemoryTileProvider;
    private final Provider<UiModeNightTile> mUiModeNightTileProvider;
    private final Provider<ScreenRecordTile> mScreenRecordTileProvider;

    /*UNISOC Bug 1074234, 885650, Super power feature @{ */
    private final Provider<SuperBatteryTile> mSuperBatteryTileProvider;
    /* @} */

    private final Lazy<QSHost> mQsHostLazy;

    /* UNISOC: Modify for bug1335095 @{ */
    private VolteTile mVolte1Tile = null;
    private VolteTile mVolte2Tile = null;
    private VoWifiTile mVoWifiTile = null;
    private LteServiceTile mLte1Tile = null;
    private LteServiceTile mLte2Tile = null;
    private CellularTile mCellularTile = null;
    /* @} */

    @Inject
    public QSFactoryImpl(Lazy<QSHost> qsHostLazy,
            Provider<WifiTile> wifiTileProvider,
            Provider<BluetoothTile> bluetoothTileProvider,
            Provider<CellularTile> cellularTileProvider,
            Provider<DndTile> dndTileProvider,
            Provider<ColorInversionTile> colorInversionTileProvider,
            Provider<AirplaneModeTile> airplaneModeTileProvider,
            Provider<WorkModeTile> workModeTileProvider,
            Provider<RotationLockTile> rotationLockTileProvider,
            Provider<FlashlightTile> flashlightTileProvider,
            Provider<LongScreenshotTile> longScreenshotTileProvider,
            Provider<ScreenshotTile> screenshotTileProvider,
            Provider<LocationTile> locationTileProvider,
            Provider<CastTile> castTileProvider,
            Provider<HotspotTile> hotspotTileProvider,
            Provider<UserTile> userTileProvider,
            Provider<BatterySaverTile> batterySaverTileProvider,
            Provider<DataSaverTile> dataSaverTileProvider,
            Provider<NightDisplayTile> nightDisplayTileProvider,
            Provider<NfcTile> nfcTileProvider,
            Provider<GarbageMonitor.MemoryTile> memoryTileProvider,
            Provider<UiModeNightTile> uiModeNightTileProvider,
            Provider<SuperBatteryTile> superBatteryTileProvider,//UNISOC Bug 1074234, 885650, Super power feature
            Provider<ScreenRecordTile> screenRecordTileProvider) {
        mQsHostLazy = qsHostLazy;
        mWifiTileProvider = wifiTileProvider;
        mBluetoothTileProvider = bluetoothTileProvider;
        mCellularTileProvider = cellularTileProvider;
        mDndTileProvider = dndTileProvider;
        mColorInversionTileProvider = colorInversionTileProvider;
        mAirplaneModeTileProvider = airplaneModeTileProvider;
        mWorkModeTileProvider = workModeTileProvider;
        mRotationLockTileProvider = rotationLockTileProvider;
        mFlashlightTileProvider = flashlightTileProvider;
        mLongScreenshotTileProvider = longScreenshotTileProvider;
        mScreenshotTileProvider = screenshotTileProvider;
        mLocationTileProvider = locationTileProvider;
        mCastTileProvider = castTileProvider;
        mHotspotTileProvider = hotspotTileProvider;
        mUserTileProvider = userTileProvider;
        mBatterySaverTileProvider = batterySaverTileProvider;
        mDataSaverTileProvider = dataSaverTileProvider;
        mNightDisplayTileProvider = nightDisplayTileProvider;
        mNfcTileProvider = nfcTileProvider;
        mMemoryTileProvider = memoryTileProvider;
        mUiModeNightTileProvider = uiModeNightTileProvider;
        /*UNISOC Bug 1074234, 885650, Super power feature @{ */
        mSuperBatteryTileProvider = superBatteryTileProvider;
        /* @} */
        mScreenRecordTileProvider = screenRecordTileProvider;
    }

    public QSTile createTile(String tileSpec) {
        QSTileImpl tile = createTileInternal(tileSpec);
        if (tile != null) {
            tile.handleStale(); // Tile was just created, must be stale.
        }
        return tile;
    }

    private QSTileImpl createTileInternal(String tileSpec) {
        // Stock tiles.
        switch (tileSpec) {
            case "wifi":
                return mWifiTileProvider.get();
            case "volte1":
            case "volte2":
            case "vowifi":
            case "lte": //UNISOC: Modify for bug1263324
            case "lte1":
            case "lte2":
                return createExtraTile(tileSpec);
            case "bt":
                return mBluetoothTileProvider.get();
            case "cell":
                /* UNISOC: Modify for bug1335095 @{ */
                if (mCellularTile != null) {
                    mCellularTile.unregisterListen();
                }
                mCellularTile = mCellularTileProvider.get();
                return mCellularTile;
                /* @} */
            case "dnd":
                return mDndTileProvider.get();
            case "inversion":
                return mColorInversionTileProvider.get();
            case "airplane":
                return mAirplaneModeTileProvider.get();
            case "work":
                return mWorkModeTileProvider.get();
            case "rotation":
                return mRotationLockTileProvider.get();
            case "flashlight":
                return mFlashlightTileProvider.get();
            case "longscreenshot":
                return mLongScreenshotTileProvider.get();
            case "screenshot":
                return mScreenshotTileProvider.get();
            case "location":
                return mLocationTileProvider.get();
            case "cast":
                return mCastTileProvider.get();
            case "hotspot":
                return mHotspotTileProvider.get();
            case "user":
                return mUserTileProvider.get();
            case "battery":
                return mBatterySaverTileProvider.get();
            case "saver":
                return mDataSaverTileProvider.get();
            case "night":
                return mNightDisplayTileProvider.get();
            case "nfc":
                return mNfcTileProvider.get();
            case "dark":
                return mUiModeNightTileProvider.get();
            case "screenrecord":
                return mScreenRecordTileProvider.get();
            /*UNISOC Bug 1074234, 885650, Super power feature @{ */
            case "superbattery":
                if (UnisocPowerManagerUtil.SUPPORT_SUPER_POWER_SAVE) {
                    return mSuperBatteryTileProvider.get();
                } else {
                    return null;
                }
            /* @} */
        }

        // Custom tiles
        if (tileSpec.startsWith(CustomTile.PREFIX)) {
            return CustomTile.create(mQsHostLazy.get(), tileSpec,
                    mQsHostLazy.get().getUserContext());
        }

        // Debug tiles.
        /* UNISOC bug 908966 control MemoryTile by ro.systemui.debug_memory @{ */
        boolean debugMemory = SystemProperties.getBoolean("systemui.debug_memory",false);
        if (Build.IS_DEBUGGABLE && debugMemory) {
        /* @} */
            if (tileSpec.equals(GarbageMonitor.MemoryTile.TILE_SPEC)) {
                return mMemoryTileProvider.get();
            }
        }

        // Broken tiles.
        Log.w(TAG, "No stock tile spec: " + tileSpec);
        return null;
    }

    @Override
    public QSTileView createTileView(QSTile tile, boolean collapsedView) {
        Context context = new ContextThemeWrapper(mQsHostLazy.get().getContext(), R.style.qs_theme);
        QSIconView icon = tile.createTileView(context);
        if (collapsedView) {
            return new QSTileBaseView(context, icon, collapsedView);
        } else {
            return new com.android.systemui.qs.tileimpl.QSTileView(context, icon);
        }
    }

    /* UNISOC: Modify for bug1335095 @{ */
    public QSTileImpl createExtraTile(String tileSpec) {
        Context context = mQsHostLazy.get().getContext();
        if ("volte1".equals(tileSpec)
                && context.getResources().getBoolean(com.android.internal.R.bool.config_device_volte_available)
                && context.getResources().getBoolean(R.bool.config_show_volte_tile)
                && isDeviceSupportLte()) {
            if (mVolte1Tile != null) {
                mVolte1Tile.unregisterListen();
            }
            mVolte1Tile = new VolteTile(mQsHostLazy.get(),0);
            return mVolte1Tile;
        } else if ("volte2".equals(tileSpec)
                && context.getResources().getBoolean(com.android.internal.R.bool.config_device_volte_available)
                && context.getResources().getBoolean(R.bool.config_show_volte_tile)
                && isDeviceSupportDualLte()) {
            if (mVolte2Tile != null) {
                mVolte2Tile.unregisterListen();
            }
            mVolte2Tile = new VolteTile(mQsHostLazy.get(),1);
            return mVolte2Tile;
        } else if ("vowifi".equals(tileSpec)
                && context.getResources().getBoolean(com.android.internal.R.bool.config_device_wfc_ims_available)
                && context.getResources().getBoolean(R.bool.config_show_vowifi_tile)){
            if (mVoWifiTile != null) {
                mVoWifiTile.unregisterListen();
            }
            mVoWifiTile = new VoWifiTile(mQsHostLazy.get());
            return mVoWifiTile;
        } else if (("lte1".equals(tileSpec) || "lte".equals(tileSpec)) //UNISOC: Modify for bug1263324
                && context.getResources().getBoolean(R.bool.config_show_lte_tile)
                && isDeviceSupportLte()) {
            if (mLte1Tile != null) {
                mLte1Tile.unregisterListen();
            }
            mLte1Tile = new LteServiceTile(mQsHostLazy.get());
            return mLte1Tile;
        } else if ("lte2".equals(tileSpec)
                && context.getResources().getBoolean(R.bool.config_show_lte_tile)
                && isDeviceSupportDualLte()) {
            if (mLte2Tile != null) {
                mLte2Tile.unregisterListen();
            }
            mLte2Tile = new LteServiceTile(mQsHostLazy.get(),1);
            return mLte2Tile;
        }
        return null;
    }
    /* @} */

    public static boolean isDeviceSupportLte() {
        String prop = SystemProperties.get(MODEM_CONFIG_PROP, "");
        Log.d(TAG, "isDeviceSupportLte prop = " + prop);
        if (!prop.isEmpty() && prop.toUpperCase().contains(LTE_INDICATOR)) {
            return true;
        }
        return false;
    }

    public static boolean isDeviceSupportDualLte() {
        String[] modemConfigs = SystemProperties.get(MODEM_CONFIG_PROP, "").split(",");
        boolean isMultiSim = !"ssss".equals(SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG, "ssss"));
        return modemConfigs.length > 1
                && modemConfigs[0].contains(LTE_INDICATOR)
                && modemConfigs[1].contains(LTE_INDICATOR)
                && isMultiSim;
    }
}
